import requests
import time
import typing as tp
from datetime import datetime
import threading
from pynput import keyboard
import re  # 用于正则表达式匹配

class TypingService:
    """
    与打字统计后端服务进行交互的类
    """
    
    def __init__(self, base_url: str = "http://localhost:8000"):
        """
        初始化 TypingService 类
        
        参数:
            base_url: 后端服务的基础 URL
        """
        self.base_url = base_url.rstrip('/')
    
    def add_text(self, text: str) -> tp.Dict[str, tp.Any]:
        """
        向服务器添加文本
        
        参数:
            text: 要添加的文本
            
        返回:
            包含操作状态的字典
        """
        try:
            response = requests.get(f"{self.base_url}/load", params={"text": text})
            response.raise_for_status()
            return response.json()
        except requests.RequestException as e:
            return {"status": "error", "message": str(e)}
    
    def get_statistics(self) -> tp.Dict[str, tp.Any]:
        """
        获取打字文本的统计信息
        
        返回:
            包含统计信息的字典
        """
        try:
            response = requests.get(f"{self.base_url}/statistic")
            response.raise_for_status()
            return response.json()
        except requests.RequestException as e:
            return {"status": "error", "message": str(e)}
    
    def get_formatted_statistics(self) -> str:
        """
        获取格式化的统计信息字符串
        
        返回:
            格式化的统计信息字符串
        """
        stats = self.get_statistics()
        
        if stats.get("status") != "success":
            return f"获取统计信息失败: {stats.get('message', '未知错误')}"
        
        statistics = stats.get("statistics", {})
        
        if not statistics.get("file_exists", False):
            return "尚无打字记录"
        
        return (
            f"统计信息:\n"
            f"- 总行数: {statistics.get('total_lines', 0)}\n"
            f"- 总字符数: {statistics.get('total_characters', 0)}\n"
            f"- 不含空格的字符数: {statistics.get('total_characters_no_spaces', 0)}\n"
            f"- 总词数: {statistics.get('total_words', 0)}"
        )


class TypingTracker:
    """
    莫斯码输入跟踪器，将莫斯码转换为英文字母，可选支持日语平假名转换
    """
    
    def __init__(self, service: TypingService = None, dot: str = ".", dash: str = "-", 
                 upload_key: str = "------", is_japanese: bool = False):
        """
        初始化莫斯码输入跟踪器
        
        参数:
            service: 用于与后端通信的 TypingService 实例
            dot: 表示莫斯码"点"的字符串，默认为"."
            dash: 表示莫斯码"杠"的字符串，默认为"-"
            upload_key: 触发自动上传的键或序列，默认为"------"(六个杠)
            is_japanese: 是否启用日语平假名转换，默认为False
        """
        self.service = service or TypingService()
        self.dot = dot
        self.dash = dash
        self.upload_key = upload_key
        self.is_japanese = is_japanese
        self.current_code = ""
        self.current_message = ""
        self.is_active = False
        self.timer = None
        self.timeout = 1.0  # 定时器超时时间（秒）
        
        # 用于检测上传键序列的缓冲区
        self.sequence_buffer = ""
        
        # 莫斯码到英文字母的映射字典
        self.morse_to_char = {
            ".-": "A", "-...": "B", "-.-.": "C", "-..": "D", ".": "E",
            "..-.": "F", "--.": "G", "....": "H", "..": "I", ".---": "J",
            "-.-": "K", ".-..": "L", "--": "M", "-.": "N", "---": "O",
            ".--.": "P", "--.-": "Q", ".-.": "R", "...": "S", "-": "T",
            "..-": "U", "...-": "V", ".--": "W", "-..-": "X", "-.--": "Y",
            "--..": "Z", ".----": "1", "..---": "2", "...--": "3", "....-": "4",
            ".....": "5", "-....": "6", "--...": "7", "---..": "8", "----.": "9",
            "-----": "0", ".-.-.-": ".", "--..--": ",", "..--..": "?",
            ".----.": "'", "-.-.--": "!", "-..-.": "/", "-.--.": "(", 
            "-.--.-": ")", ".-...": "&", "---...": ":", "-.-.-.": ";",
            "-...-": "=", ".-.-.": "+", "-....-": "-", "..--.-": "_",
            ".-..-.": "\"", "...-..-": "$", ".--.-.": "@", "": " ",
            "......": "BACKSPACE",  # 六个点对应退格键
            "------": "UPLOAD",     # 六个杠对应上传功能
            ".-----": "CUSTOM1",    # 一点五杠对应自定义功能1
            "..----": "CUSTOM2",    # 两点四杠对应自定义功能2
            "...---": "CUSTOM3",    # 三点三杠对应自定义功能3
            "....--": "CUSTOM4",    # 四点两杠对应自定义功能4
            ".....--": "CUSTOM5"    # 五点两杠对应自定义功能5
        }
        
        # 英文字母到莫斯码的映射字典（用于参考）
        self.char_to_morse = {v: k for k, v in self.morse_to_char.items()}
        
        # 罗马字到平假名的映射
        self.romaji_to_hiragana = {
            # 基本假名
            "A": "あ", "I": "い", "U": "う", "E": "え", "O": "お",
            "KA": "か", "KI": "き", "KU": "く", "KE": "け", "KO": "こ",
            "SA": "さ", "SHI": "し", "SU": "す", "SE": "せ", "SO": "そ",
            "TA": "た", "CHI": "ち", "TSU": "つ", "TE": "て", "TO": "と",
            "NA": "な", "NI": "に", "NU": "ぬ", "NE": "ね", "NO": "の",
            "HA": "は", "HI": "ひ", "FU": "ふ", "HE": "へ", "HO": "ほ",
            "MA": "ま", "MI": "み", "MU": "む", "ME": "め", "MO": "も",
            "YA": "や", "YU": "ゆ", "YO": "よ",
            "RA": "ら", "RI": "り", "RU": "る", "RE": "れ", "RO": "ろ",
            "WA": "わ", "WO": "を", "NN": "ん",
            
            # 浊音
            "GA": "が", "GI": "ぎ", "GU": "ぐ", "GE": "げ", "GO": "ご",
            "ZA": "ざ", "JI": "じ", "ZU": "ず", "ZE": "ぜ", "ZO": "ぞ",
            "DA": "だ", "DI": "ぢ", "DU": "づ", "DE": "で", "DO": "ど",
            "BA": "ば", "BI": "び", "BU": "ぶ", "BE": "べ", "BO": "ぼ",
            "PA": "ぱ", "PI": "ぴ", "PU": "ぷ", "PE": "ぺ", "PO": "ぽ",
            
            # 拗音
            "KYA": "きゃ", "KYU": "きゅ", "KYO": "きょ",
            "SHA": "しゃ", "SHU": "しゅ", "SHO": "しょ",
            "CHA": "ちゃ", "CHU": "ちゅ", "CHO": "ちょ",
            "NYA": "にゃ", "NYU": "にゅ", "NYO": "にょ",
            "HYA": "ひゃ", "HYU": "ひゅ", "HYO": "ひょ",
            "MYA": "みゃ", "MYU": "みゅ", "MYO": "みょ",
            "RYA": "りゃ", "RYU": "りゅ", "RYO": "りょ",
            "GYA": "ぎゃ", "GYU": "ぎゅ", "GYO": "ぎょ",
            "JA": "じゃ", "JU": "じゅ", "JO": "じょ",
            "BYA": "びゃ", "BYU": "びゅ", "BYO": "びょ",
            "PYA": "ぴゃ", "PYU": "ぴゅ", "PYO": "ぴょ",
            
            # 小假名
            "XA": "ぁ", "XI": "ぃ", "XU": "ぅ", "XE": "ぇ", "XO": "ぉ",
            "XYA": "ゃ", "XYU": "ゅ", "XYO": "ょ",
            "XTSU": "っ",
            
            # 小假名 - L前缀
            "LA": "ぁ", "LI": "ぃ", "LU": "ぅ", "LE": "ぇ", "LO": "ぉ",
            "LYA": "ゃ", "LYU": "ゅ", "LYO": "ょ",
            "LTSU": "っ", "LTU": "っ",
            "LWA": "ゎ", "LKA": "ゕ", "LKE": "ゖ",
            
            # 促音/双辅音
            "KKA": "っか", "KKI": "っき", "KKU": "っく", "KKE": "っけ", "KKO": "っこ",
            "SSA": "っさ", "SSHI": "っし", "SSU": "っす", "SSE": "っせ", "SSO": "っそ",
            "TTA": "った", "TCHI": "っち", "TTSU": "っつ", "TTE": "って", "TTO": "っと",
            "PPA": "っぱ", "PPI": "っぴ", "PPU": "っぷ", "PPE": "っぺ", "PPO": "っぽ",
            
            # 促音+拗音组合
            "KKYA": "っきゃ", "KKYU": "っきゅ", "KKYO": "っきょ",
            "SSHA": "っしゃ", "SSHU": "っしゅ", "SSHO": "っしょ",
            "CCHA": "っちゃ", "CCHU": "っちゅ", "CCHO": "っちょ",
            "PPYA": "っぴゃ", "PPYU": "っぴゅ", "PPYO": "っぴょ",
            
            # 常见双辅音的其他情况
            "TTA": "った", "TTI": "っち", "TTU": "っつ", "TTE": "って", "TTO": "っと",
            "GGA": "っが", "GGI": "っぎ", "GGU": "っぐ", "GGE": "っげ", "GGO": "っご",
            "ZZA": "っざ", "ZZI": "っじ", "ZZU": "っず", "ZZE": "っぜ", "ZZO": "っぞ",
            "DDA": "っだ", "DDI": "っぢ", "DDU": "っづ", "DDE": "っで", "DDO": "っど",
            "BBA": "っば", "BBI": "っび", "BBU": "っぶ", "BBE": "っべ", "BBO": "っぼ",
            
            # 自定义输入与实际发音的对应
            "XTSUA": "っぁ", "XTSUI": "っぃ", "XTSUU": "っぅ", "XTSUE": "っぇ", "XTSUO": "っぉ",
            
            # 另一种表示促音的方式
            "XTU": "っ", "XTSU": "っ",
            
            # n 音特殊规则
            "NNA": "んあ", "NNI": "んい", "NNU": "んう", "NNE": "んえ", "NNO": "んお",
        }
    
    def start(self):
        """
        开始莫斯码输入会话
        """
        self.current_code = ""
        self.current_message = ""
        self.is_active = True
        if self.timer:
            self.timer.cancel()
            self.timer = None
        print(f"莫斯码输入已开始，使用 '{self.dot}' 表示点，'{self.dash}' 表示杠")
        print("输入后等待1秒将自动转换为字母")
    
    def stop(self):
        """
        停止莫斯码输入会话
        """
        if not self.is_active:
            print("没有活动的输入会话")
            return
        
        if self.timer:
            self.timer.cancel()
            self.timer = None
        
        # 处理最后一个未完成的莫斯码
        if self.current_code:
            self._convert_current_code()
        
        self.is_active = False
        print("莫斯码输入已停止")
        
        # 上传最终消息到服务器
        if self.current_message:
            self.service.add_text(self.current_message)
        
        return self.current_message
    
    def _convert_current_code(self):
        """
        将当前莫斯码转换为字符并添加到消息中
        """
        if not self.current_code:
            return
        
        char = self.morse_to_char.get(self.current_code, "?")
        
        # 检查是否为特殊操作
        if char == "BACKSPACE":
            # 如果当前消息不为空，删除最后一个字符
            if self.current_message:
                self.current_message = self.current_message[:-1]
                print("退格：删除最后一个字符")
            else:
                print("退格：缓冲区为空，无法删除")
        elif char == "UPLOAD":
            # 执行上传功能
            self._upload_function()
        elif char == "CUSTOM1":
            self._custom_function1()
        elif char == "CUSTOM2":
            self._custom_function2()
        elif char == "CUSTOM3":
            self._custom_function3()
        elif char == "CUSTOM4":
            self._custom_function4()
        elif char == "CUSTOM5":
            self._custom_function5()
        else:
            # 正常字符，添加到消息中
            self.current_message += char
            print(f"解析为: {char}")
        
        print(f"当前消息: {self.current_message}")
        self.current_code = ""
    
    # 自定义功能函数
    def _custom_function1(self):
        """
        自定义功能1（一点五杠 .-----）
        """
        print("执行自定义功能1")
        # 在此处添加自定义功能1的实现
    
    def _custom_function2(self):
        """
        自定义功能2（两点四杠 ..----）
        """
        print("执行自定义功能2")
        # 在此处添加自定义功能2的实现
    
    def _custom_function3(self):
        """
        自定义功能3（三点三杠 ...---）
        """
        print("执行自定义功能3")
        # 在此处添加自定义功能3的实现
    
    def _custom_function4(self):
        """
        自定义功能4（四点两杠 ....--）
        """
        print("执行自定义功能4")
        # 在此处添加自定义功能4的实现
    
    def _custom_function5(self):
        """
        自定义功能5（五点两杠 .....--）
        """
        print("执行自定义功能5")
        # 在此处添加自定义功能5的实现
    
    def _reset_timer(self):
        """
        重置定时器
        """
        if self.timer:
            self.timer.cancel()
        
        self.timer = threading.Timer(self.timeout, self._convert_current_code)
        self.timer.daemon = True  # 设置为守护线程，这样主程序退出时不会阻塞
        self.timer.start()
    
    def _convert_to_hiragana(self, text):
        """
        将英文字母组合转换为日语平假名
        
        参数:
            text: 要转换的英文字母文本
            
        返回:
            转换后的文本，不可转换的部分保持原样
        """
        if not self.is_japanese:
            return text
            
        # 转换为大写
        upper_text = text.upper()
        
        # 创建一个正则表达式模式来匹配所有可能的罗马字组合
        # 按长度排序，首先尝试匹配最长的组合
        patterns = sorted(self.romaji_to_hiragana.keys(), key=len, reverse=True)
        
        # 进行转换
        result = ""
        i = 0
        while i < len(upper_text):
            matched = False
            # 尝试从最长的模式开始匹配
            for pattern in patterns:
                if upper_text[i:].startswith(pattern):
                    result += self.romaji_to_hiragana[pattern]
                    i += len(pattern)
                    matched = True
                    break
            # 如果没有匹配到任何模式，保留原字符
            if not matched:
                result += upper_text[i]
                i += 1
        
        print(f"日语转换: {text} -> {result}")
        return result
    
    def _upload_function(self):
        """
        上传功能（六个杠 ------）
        """
        print("执行上传功能")
        self._upload_current_message()
    
    def _upload_current_message(self):
        """
        上传当前消息到服务器并清除缓冲区
        """
        # 上传消息到服务器
        if self.current_message:
            # 如果启用了日语模式，转换为平假名
            if self.is_japanese:
                converted_message = self._convert_to_hiragana(self.current_message)
                print(f"上传消息(日语模式): {self.current_message} -> {converted_message}")
                self.service.add_text(converted_message)
            else:
                print(f"上传消息: {self.current_message}")
                self.service.add_text(self.current_message)
                
            self.current_message = ""  # 清除消息缓冲区
            print("缓冲区已清空，继续监听...")
    
    def process_input(self, input_text: str):
        """
        处理用户输入，将其转换为莫斯码并解析
        
        参数:
            input_text: 用户输入的文本
        """
        if not self.is_active:
            print("请先开始莫斯码输入会话")
            return
        
        # 单字符输入情况
        if len(input_text) == 1:
            # 处理单个字符
            if input_text == self.dot and self.dot != self.dash:  # 确保点和杠不重叠
                self.current_code += "."
                print(f"当前莫斯码: {self.current_code}")
                self._reset_timer()
                
            elif input_text == self.dash and self.dot != self.dash:  # 确保点和杠不重叠
                self.current_code += "-"
                print(f"当前莫斯码: {self.current_code}")
                self._reset_timer()
                
            elif input_text == " ":
                # 处理空格（词间隔）
                if self.timer:
                    self.timer.cancel()
                    self.timer = None
                
                # 先处理当前未完成的莫斯码
                if self.current_code:
                    self._convert_current_code()
                
                # 添加空格到消息
                self.current_message += " "
                print(f"当前消息: {self.current_message}")
                
            else:
                # 处理其他单字符输入
                if input_text == "\n":
                    # 换行表示结束当前输入并添加空格
                    if self.timer:
                        self.timer.cancel()
                        self.timer = None
                    
                    # 处理当前未完成的莫斯码
                    if self.current_code:
                        self._convert_current_code()
                    
                    # 添加空格到消息
                    self.current_message += " "
                    print(f"当前消息: {self.current_message}")
                else:
                    print(f"无效输入: {input_text}")
        else:
            # 处理多字符输入
            
            # 如果是莫斯码组合
            if all(c in ['.', '-'] for c in input_text):
                # 将输入的莫斯码直接添加到当前代码
                self.current_code += input_text
                print(f"当前莫斯码: {self.current_code}")
                self._reset_timer()
            else:
                print(f"无效输入: {input_text}")
    
    def get_current_message(self):
        """
        获取当前已解析的消息
        
        返回:
            当前消息字符串
        """
        return self.current_message
    
    def get_morse_reference(self):
        """
        获取莫斯码参考表
        
        返回:
            包含莫斯码参考的字符串
        """
        reference = "莫斯码参考表:\n"
        for char, code in sorted(self.char_to_morse.items()):
            if char == " ":
                continue
            reference += f"{char}: {code}\n"
        return reference

    def listen_keyboard(self, dot_key: str = '.', dash_key: str = '-', 
                        space_key: str = ' ', quit_key: str = 'q', upload_key: str = None):
        """
        实时监听键盘输入，将按键转换为莫斯码
        
        参数:
            dot_key: 表示点的键，默认为'.'
            dash_key: 表示杠的键，默认为'-'
            space_key: 表示空格的键，默认为空格键
            quit_key: 退出监听的键，默认为'q'
            upload_key: 上传的键，如果为None则使用初始化时设置的值
        """
        if not self.is_active:
            self.start()
        
        self.key_dot = dot_key
        self.key_dash = dash_key
        self.key_space = space_key
        self.key_quit = quit_key
        if upload_key is not None:
            self.upload_key = upload_key
        
        self.is_listening = True
        self.last_key_time = time.time()
        self.key_buffer = ""
        
        print(f"开始监听键盘输入:")
        print(f"- 按 '{dot_key}' 输入点")
        print(f"- 按 '{dash_key}' 输入杠")
        print(f"- 按 '{space_key}' 输入空格")
        if len(self.upload_key) == 1:
            print(f"- 按 '{self.upload_key}' 上传当前内容")
        else:
            print(f"- 输入序列 '{self.upload_key}' 上传当前内容")
        print(f"- 按 '{quit_key}' 退出监听")
        print("输入后等待1秒将自动转换为字母")
        
        # 创建一个定时器线程，用于检测输入超时
        self.input_timer = None
        self._reset_input_timer()
        
        # 开始监听键盘
        with keyboard.Listener(on_press=self._on_key_press) as listener:
            try:
                listener.join()  # 阻塞直到监听结束
            except KeyboardInterrupt:
                self.is_listening = False
                if self.input_timer:
                    self.input_timer.cancel()
                self.stop()
    
    def _on_key_press(self, key):
        """
        键盘按键事件处理函数
        """
        if not self.is_listening:
            return False  # 停止监听
        
        try:
            # 获取按键字符
            key_char = key.char
        except AttributeError:
            # 特殊键没有字符属性
            if key == keyboard.Key.space:
                key_char = ' '
            elif key == keyboard.Key.enter:
                key_char = '\n'
            else:
                return True  # 继续监听
        
        # 处理退出键
        if key_char == self.key_quit:
            print("退出监听")
            self.is_listening = False
            if self.input_timer:
                self.input_timer.cancel()
            self.stop()
            return False  # 停止监听
        
        # 重置输入定时器
        if self.input_timer:
            self.input_timer.cancel()
        
        # 处理点、杠和空格
        if key_char == self.key_dot:
            self.key_buffer += "."
            print(".", end="", flush=True)
            self._reset_input_timer()
                
        elif key_char == self.key_dash:
            self.key_buffer += "-"
            print("-", end="", flush=True)
            self._reset_input_timer()
                
        elif key_char == self.key_space:
            # 如果有未处理的莫斯码，先处理
            if self.key_buffer:
                self._process_key_buffer()
            # 添加空格到消息
            self.current_message += " "
            print(" ", end="", flush=True)
        
        return True  # 继续监听
    
    def _reset_input_timer(self):
        """
        重置输入超时定时器
        """
        if self.input_timer:
            self.input_timer.cancel()
        
        self.input_timer = threading.Timer(1.0, self._process_key_buffer)
        self.input_timer.daemon = True
        self.input_timer.start()
    
    def _process_key_buffer(self):
        """
        处理当前的按键缓冲区
        """
        if not self.key_buffer:
            return
        
        # 将莫斯码转换为字符
        char = self.morse_to_char.get(self.key_buffer, "?")
        
        # 检查是否为特殊操作
        if char == "BACKSPACE":
            # 如果当前消息不为空，删除最后一个字符
            if self.current_message:
                self.current_message = self.current_message[:-1]
                print(" -> 退格（删除最后一个字符）")
            else:
                print(" -> 退格（缓冲区为空，无法删除）")
        elif char == "UPLOAD":
            # 执行上传功能
            print(" -> 执行上传功能")
            self._upload_current_message()
        elif char == "CUSTOM1":
            self._custom_function1()
            print(" -> 执行自定义功能1")
        elif char == "CUSTOM2":
            self._custom_function2()
            print(" -> 执行自定义功能2")
        elif char == "CUSTOM3":
            self._custom_function3()
            print(" -> 执行自定义功能3")
        elif char == "CUSTOM4":
            self._custom_function4()
            print(" -> 执行自定义功能4")
        elif char == "CUSTOM5":
            self._custom_function5()
            print(" -> 执行自定义功能5")
        else:
            # 正常字符，添加到消息中
            self.current_message += char
            print(f" -> {char}")  # 打印转换结果
        
        # 清空缓冲区
        self.key_buffer = ""


# 使用示例
if __name__ == "__main__":
    tracker = TypingTracker()
    
    # 开始打字会话
    # tracker.start()
    
    # # 模拟用户输入
    # tracker.process_input(".-")
    # time.sleep(2)  # 模拟用户思考时间
    # tracker.process_input("..---")
    # time.sleep(1)
    
    # # 结束会话并获取统计信息
    # current_message = tracker.stop()
    # print(f"当前解析的消息: {current_message}")
    
    # 获取莫斯码参考表
    # morse_reference = tracker.get_morse_reference()
    # print(morse_reference)
